Projeto Final
MAC0460 - Introdução ao aprendizado de máquina
Profª Nina Hirata
A motivação original de nosso projeto é o entendimento dos padrões
climáticos e suas alterações no clima de uma das cidades mais relevantes
num cenário global: Londres. Para isso decidimos fazer um projeto do 1º
formato (utilizando um dataset público), onde a base escolhida
(london_weather.csv, obtida no website Kaggle
através desse
link) pode ser interpretada como uma série temporal, a medida que
mede as variações do tempo (entre 1979 e 2021) de variáveis fixadas em
um único local.
O objetivo do projeto é o uso de um algoritmo de machine learning para que o mesmo consiga prever a categoria de duas das variáveis da database (precipitação e neve) para uma nova informação adicionada ao modelo. As categorias seriam então “chove” ou “não chove” e “neva” ou “não neva”. A ideia será fazer 3 métodos distintos (Regressão Logística, KNN e Árvore de Decisão), compará-los através de suas métricas relacionadas à acurácia e ver qual tem a melhor performance/predição.
A base de dados escolhida foi criada a partir da união de medições oriundas de pedidos de atributos individuais do clima providos pela European Climate Assessment (ECA). As medidas desta base de dados em particular foram gravadas pela estação climática nas redondezas do Aeroporto Heathrow em Londres, Reino Unido. O tamanho original da base de dados escolhida, assim como uma lista dos atributos e suas descrições, está descrito abaixo:
london_weather.csv - 15341 observações x 10
atributos:
date - data em que ocorreu a medição -
(int)
cloud_cover - medição da nebulosidade em oktas -
(float)
sunshine - medição da luz solar em horas (hrs) -
(float)
global_radiation - irradiação medida Watt por metro
quadrado (W/m2) - (float)
max_temp - temperatura máxima registrada em graus
Celsius (°C) - (float)
mean_temp - temperatura média registrada em graus
Celsius (°C) - (float)
min_temp - temperatura mínima registrada em graus
Celsius (°C) - (float)
precipitation - precipitação medida em milímetros
(mm) - (float)
pressure - pressão medida em Pascals (Pa) -
(float)
snow_depth - profundidade da neve medida em
centímetros (cm) - (float)
import pandas as pd
import numpy as np
url = 'https://raw.githubusercontent.com/bmorbin/ML_Project/main/data_raw.csv'
data = pd.read_csv(url)
print(data.head(5)) # Print raw data
date cloud_cover sunshine ... precipitation pressure snow_depth
0 19790101 2.0 7.0 ... 0.4 101900.0 9.0
1 19790102 6.0 1.7 ... 0.0 102530.0 8.0
2 19790103 5.0 0.0 ... 0.0 102050.0 4.0
3 19790104 8.0 0.0 ... 0.0 100840.0 2.0
4 19790105 6.0 2.0 ... 0.0 102250.0 1.0
[5 rows x 10 columns]
print(data.isna().sum()) # Print count of NA for each column
date 0
cloud_cover 19
sunshine 0
global_radiation 19
max_temp 6
mean_temp 36
min_temp 2
precipitation 6
pressure 4
snow_depth 1441
dtype: int64
data = data.dropna(subset=[col for col in data.columns if col!='snow_depth']) # Removing rows with NA, except the column snow_depth
print(data.isna().sum()) # Print count of NA again after delete some NA
date 0
cloud_cover 0
sunshine 0
global_radiation 0
max_temp 0
mean_temp 0
min_temp 0
precipitation 0
pressure 0
snow_depth 1418
dtype: int64
from sklearn.linear_model import LinearRegression # Applying simple regression model to predict missing values from snow_depth
def reg_simple(data):
'''
A function to predict snow depth by mean temperature of the day
Returns the maximum snow depth value predict
'''
data_reg_train = data.dropna()
X_reg_train = np.array(data_reg_train.mean_temp).reshape(-1,1)
y_reg_train = np.array(data_reg_train.snow_depth).reshape(-1,1)
reg = LinearRegression()
reg.fit(X_reg_train, y_reg_train)
data_NA = data[data['snow_depth'].isna()]
y_pred = reg.predict(np.array(data_NA.mean_temp).reshape(-1,1))
return(round(max(y_pred)[0],1))
print(f'Minimum snow depth predicted is {reg_simple(data)}')
Minimum snow depth predicted is 0.2
data.snow_depth[data['snow_depth'].isna()] = 0 # So the conclusion is to input 0s in missing values from column snow_depth
print(data.isna().sum()) # Print count of NA again after input NA values from snow_depth
date 0
cloud_cover 0
sunshine 0
global_radiation 0
max_temp 0
mean_temp 0
min_temp 0
precipitation 0
pressure 0
snow_depth 0
dtype: int64
data['date'] = pd.to_datetime(data['date'].astype(str), format = "%Y%m%d") # Convert column date to pandas date type
data['month'] = data['date'].dt.month.astype(str) # Creating column month
data['rain'] = ["1" if p > 0 else "0" for p in data['precipitation']] # Creating column rain indicator
data['snow'] = ["1" if p > 0 else "0" for p in data['snow_depth']] # Creating column snow indicator
data = data.set_index('date') # Set column date to index
print(round(data[['snow','rain']].value_counts(normalize=True),3)) # Print proportion of time wich rains and snows
snow rain
0 0 0.515
1 0.476
1 1 0.005
0 0.004
dtype: float64
print(data.describe()) # Describe dataframe
cloud_cover sunshine ... pressure snow_depth
count 15261.000000 15261.000000 ... 15261.000000 15261.000000
mean 5.271018 4.345633 ... 101535.436079 0.034336
std 2.067743 4.019266 ... 1049.536452 0.519855
min 0.000000 0.000000 ... 95960.000000 0.000000
25% 4.000000 0.500000 ... 100920.000000 0.000000
50% 6.000000 3.500000 ... 101620.000000 0.000000
75% 7.000000 7.200000 ... 102240.000000 0.000000
max 9.000000 16.000000 ... 104820.000000 22.000000
[8 rows x 9 columns]
DT::datatable(py$data)
Primeiramente devemos encontrar uma solução baseline para o problema proposto. Usando a intuição e o senso comum imagina-se que, em dias muito frios, haverá uma maior probabilidade de nevar, enquanto que dias mais quentes terão maior incidência de chuva e sem neve. Tomemos então isso como nossa solução baseline que será comparada aos modelos categorizados citados acima (Regressão Logística, Árvore de Decisão e KNN).